package kd.bos.openapi.demo.auth.oauth2;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import kd.bos.openapi.common.result.CustomApiResult;
import kd.bos.openapi.demo.auth.digestauth.DigestDemoTest;
import kd.bos.openapi.sdk.exception.APIException;
import kd.bos.openapi.sdk.util.*;
import kd.bos.openapi.security.model.ApiAuthResultDto;
import kd.bos.openapi.security.oauth.token.ApiAuthRequestDto;
import kd.bos.openapi.security.oauth.token.ApiAuthVerifyResultDto;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;

/**
 * @author johnz
 * @Deacription tokenDemo测试, 根据业务需要调用getToken获取令牌，然后缓存在调用端，在access_token过期之前（2小时内）可以调用verifyToken验证access_token有效性，并获取最新的过期时间。
 * 在access_token过期之前，调用refreshToken接口刷新access_token的有效期，从而在不换access_token的情况下继续调用开放平台API
 * 可以参考认证指南 https://vip.kingdee.com/article/489812471528707840?productLineId=29&isKnowledge=2
 * @date 2023年10月20日
 */
public class TokenDemoTest {
    private final static Logger log = Logger.getLogger(TokenDemoTest.class.getName());
    // 仅供测试使用
    static String refresh_token = "";
    // 仅供测试使用
    static String access_token = "";
    // 苍穹OpenAPI调用接口的URL前缀
    public static final String urlPrefix = PropertyUtil.getProperty("bos.env.cosmic");

    /**
     * 要演示本demo，要求苍穹6.0以上版本，同时在测试的第三方应用的accessToken认证策略中，要启用增强型Token认证
     * @param args
     */
    public static void main(String[] args) {
        getToken();
        refeshToken();
        verifyToken();
        withdrawToken();
    }

    /**
     * 获取token Demo, 使用时需要确保第三方应用的accessToken认证策略中开启增强型Token认证
     */
    public static void getToken() {
        // client_id 对应第三方应用编码，client_secret对应第三方应用accessToken认证策略中AccessToken认证密钥， username是第三方应用代理用户的userName,注意要启动代理用户并设置代理用户，accountId的需要访问的数据中心
        ApiAuthRequestDto tokenRequestDto = new ApiAuthRequestDto(PropertyUtil.getProperty("oauth2.clientId"), PropertyUtil.getProperty("oauth2.clientSecret"), PropertyUtil.getProperty("oauth2.username"), PropertyUtil.getProperty("bos.cosmic.accountId"), UUID.randomUUID().toString(), DateUtil.format(new Date(), SignUtils.SIGNATUR_TIME_FORMAT), "zh_CN");
        // 获取查询结果
        String sortUrl = "kapi/oauth2/getToken";
        // 请求结果
        String res = HttpClientUtil.post(urlPrefix + sortUrl, new HashMap<>(), JSON.toJSONString(tokenRequestDto));
        CustomApiResult<ApiAuthResultDto> result = JSON.parseObject(res, new TypeReference<CustomApiResult<ApiAuthResultDto>>() {
        });
        if (!result.isStatus()) {
            log.info("res:"+res);
            throw new APIException("ERROR", "FAILED:" + result.getMessage());
        }
        refresh_token = result.getData().getRefresh_token();
        access_token = result.getData().getAccess_token();
        log.info("------------------------getToken result-------------------------");
        log.info(JSON.toJSONString(result, true));
    }

    /**
     * 刷新token Demo, 使用时需要确保第三方应用的accessToken认证策略中开启增强型Token认证
     * 对accessToken密钥增加有效期
     */
    public static void refeshToken() {
        Map<String, String> request = new HashMap<>();
        request.put("client_id", PropertyUtil.getProperty("oauth2.clientId"));
        request.put("grant_type", "refresh_token");
        request.put("refresh_token", refresh_token);
        request.put("language", "zh_CN");
        request.put("nonce", UUID.randomUUID().toString());
        request.put("timestamp", DateUtil.format(new Date(), SignUtils.SIGNATUR_TIME_FORMAT));

        // 获取查询结果
        String sortUrl = "kapi/oauth2/refreshToken";
        // 请求结果
        String res = HttpClientUtil.post(urlPrefix + sortUrl, new HashMap<>(), JSON.toJSONString(request));
        CustomApiResult<ApiAuthResultDto> result = JSON.parseObject(res, new TypeReference<CustomApiResult<ApiAuthResultDto>>() {
        });
        log.info("------------------------refeshToken result-------------------------");
        log.info(JSON.toJSONString(result, true));
    }

    /**
     * 验证token Demo, 使用时需要确保第三方应用的accessToken认证策略中开启增强型Token认证
     */
    public static void verifyToken() {
        Map<String, String> request = new HashMap<>();
        request.put("client_id", PropertyUtil.getProperty("oauth2.clientId"));
        request.put("token_type_hint", "access_token");
        request.put("token", access_token);
        request.put("language", "zh_CN");
        request.put("nonce", UUID.randomUUID().toString());
        request.put("timestamp", DateUtil.format(new Date(), SignUtils.SIGNATUR_TIME_FORMAT));
        // 获取查询结果
        String sortUrl = "kapi/oauth2/verifyToken";
        // 请求结果
        String res = HttpClientUtil.post(urlPrefix + sortUrl, new HashMap<>(), JSON.toJSONString(request));
        CustomApiResult<ApiAuthVerifyResultDto> result = JSON.parseObject(res, new TypeReference<CustomApiResult<ApiAuthVerifyResultDto>>() {
        });
        log.info("------------------------verifyToken result-------------------------");
        log.info(JSON.toJSONString(result, true));
    }

    /**
     * 撤回token Demo, 使用时需要确保第三方应用的accessToken认证策略中开启增强型Token认证
     */
    public static void withdrawToken() {
        Map<String, String> request = new HashMap<>();
        request.put("client_id", PropertyUtil.getProperty("oauth2.clientId"));
        request.put("client_secret", PropertyUtil.getProperty("oauth2.clientSecret"));
        request.put("token_type_hint", "access_token");
        request.put("token", access_token);
        request.put("language", "zh_CN");
        request.put("nonce", UUID.randomUUID().toString());
        request.put("timestamp", DateUtil.format(new Date(), SignUtils.SIGNATUR_TIME_FORMAT));
        // 获取查询结果
        String sortUrl = "kapi/oauth2/withdrawToken";
        // 请求结果
        String res = HttpClientUtil.post(urlPrefix + sortUrl, new HashMap<>(), JSON.toJSONString(request));
        CustomApiResult result = JSON.parseObject(res, CustomApiResult.class);
        log.info("------------------------withdrawToken result-------------------------");
        log.info(JSON.toJSONString(result, true));
    }
}
